#include "RedisWrapper.h"
#include <sw/redis++/redis++.h>
#include <iostream>

using namespace sw::redis;

RedisWrapper::RedisWrapper(const std::string& uri) {
    try {
        redis_ = std::make_shared<Redis>(uri);
    } catch (const Error& e) {
        std::cerr << "Failed to connect to Redis: " << e.what() << std::endl;
        throw;
    }
}

// String operations
bool RedisWrapper::set(const std::string& key, const std::string& value) {
    try {
        redis_->set(key, value);
        return true;
    } catch (const Error& e) {
        std::cerr << "Redis SET error: " << e.what() << std::endl;
        return false;
    }
}

std::optional<std::string> RedisWrapper::get(const std::string& key) {
    try {
        return redis_->get(key);
    } catch (const Error& e) {
        std::cerr << "Redis GET error: " << e.what() << std::endl;
        return std::nullopt;
    }
}

bool RedisWrapper::del(const std::string& key) {
    try {
        return redis_->del(key) > 0;
    } catch (const Error& e) {
        std::cerr << "Redis DEL error: " << e.what() << std::endl;
        return false;
    }
}

bool RedisWrapper::exists(const std::string& key) {
    try {
        return redis_->exists(key);
    } catch (const Error& e) {
        std::cerr << "Redis EXISTS error: " << e.what() << std::endl;
        return false;
    }
}

// List operations
long long RedisWrapper::lpush(const std::string& key, const std::string& value) {
    try {
        return redis_->lpush(key, value);
    } catch (const Error& e) {
        std::cerr << "Redis LPUSH error: " << e.what() << std::endl;
        return -1;
    }
}

long long RedisWrapper::rpush(const std::string& key, const std::string& value) {
    try {
        return redis_->rpush(key, value);
    } catch (const Error& e) {
        std::cerr << "Redis RPUSH error: " << e.what() << std::endl;
        return -1;
    }
}

std::optional<std::string> RedisWrapper::lpop(const std::string& key) {
    try {
        return redis_->lpop(key);
    } catch (const Error& e) {
        std::cerr << "Redis LPOP error: " << e.what() << std::endl;
        return std::nullopt;
    }
}

std::optional<std::string> RedisWrapper::rpop(const std::string& key) {
    try {
        return redis_->rpop(key);
    } catch (const Error& e) {
        std::cerr << "Redis RPOP error: " << e.what() << std::endl;
        return std::nullopt;
    }
}

// Hash operations
bool RedisWrapper::hset(const std::string& key, const std::string& field, const std::string& value) {
    try {
        redis_->hset(key, field, value);
        return true;
    } catch (const Error& e) {
        std::cerr << "Redis HSET error: " << e.what() << std::endl;
        return false;
    }
}

std::optional<std::string> RedisWrapper::hget(const std::string& key, const std::string& field) {
    try {
        return redis_->hget(key, field);
    } catch (const Error& e) {
        std::cerr << "Redis HGET error: " << e.what() << std::endl;
        return std::nullopt;
    }
}

bool RedisWrapper::hdel(const std::string& key, const std::string& field) {
    try {
        return redis_->hdel(key, field) > 0;
    } catch (const Error& e) {
        std::cerr << "Redis HDEL error: " << e.what() << std::endl;
        return false;
    }
}

std::unordered_map<std::string, std::string> RedisWrapper::hgetall(const std::string& key) {
    try {
        std::unordered_map<std::string, std::string> result;
        redis_->hgetall(key, std::inserter(result, result.end()));
        return result;
    } catch (const Error& e) {
        std::cerr << "Redis HGETALL error: " << e.what() << std::endl;
        return {};
    }
}

// Set operations
bool RedisWrapper::sadd(const std::string& key, const std::string& member) {
    try {
        return redis_->sadd(key, member) > 0;
    } catch (const Error& e) {
        std::cerr << "Redis SADD error: " << e.what() << std::endl;
        return false;
    }
}

bool RedisWrapper::sismember(const std::string& key, const std::string& member) {
    try {
        return redis_->sismember(key, member);
    } catch (const Error& e) {
        std::cerr << "Redis SISMEMBER error: " << e.what() << std::endl;
        return false;
    }
}

long long RedisWrapper::scard(const std::string& key) {
    try {
        return redis_->scard(key);
    } catch (const Error& e) {
        std::cerr << "Redis SCARD error: " << e.what() << std::endl;
        return -1;
    }
}

std::vector<std::string> RedisWrapper::smembers(const std::string& key) {
    try {
        std::vector<std::string> result;
        redis_->smembers(key, std::back_inserter(result));
        return result;
    } catch (const Error& e) {
        std::cerr << "Redis SMEMBERS error: " << e.what() << std::endl;
        return {};
    }
}

// Sorted set operations
bool RedisWrapper::zadd(const std::string& key, double score, const std::string& member) {
    try {
        redis_->zadd(key, score, member);
        return true;
    } catch (const Error& e) {
        std::cerr << "Redis ZADD error: " << e.what() << std::endl;
        return false;
    }
}

std::optional<double> RedisWrapper::zscore(const std::string& key, const std::string& member) {
    try {
        return redis_->zscore(key, member);
    } catch (const Error& e) {
        std::cerr << "Redis ZSCORE error: " << e.what() << std::endl;
        return std::nullopt;
    }
}

long long RedisWrapper::zcard(const std::string& key) {
    try {
        return redis_->zcard(key);
    } catch (const Error& e) {
        std::cerr << "Redis ZCARD error: " << e.what() << std::endl;
        return -1;
    }
}

// Key operations
long long RedisWrapper::expire(const std::string& key, long long seconds) {
    try {
        return redis_->expire(key, seconds);
    } catch (const Error& e) {
        std::cerr << "Redis EXPIRE error: " << e.what() << std::endl;
        return -1;
    }
}

long long RedisWrapper::ttl(const std::string& key) {
    try {
        return redis_->ttl(key);
    } catch (const Error& e) {
        std::cerr << "Redis TTL error: " << e.what() << std::endl;
        return -1;
    }
}